#ifndef _COMMAND_H_
#define _COMMAND_H_ 1

#include <string>
#include "editor.h"
class Command{
public:
  Command(std::string str,Editor *editor)
   :action(std::move(str)),editor(editor){
  
  };
  virtual ~Command(){};
  inline std::string
  get_action(){return action;};
  virtual std::string 
  execute() = 0;
protected:
  std::string action;
  Editor *editor;
};
class ModifiedCommand:public Command{
public:
   ModifiedCommand(std::string str,Editor *editor):Command(std::move(str),editor){
   };
   virtual ~ModifiedCommand(){};
   virtual void
   undo(){
     editor->set_text(old_text); 
   };
   virtual void
   redo(){
     modify();
   }
   inline std::string 
   execute(){
     modify();
     return editor->get_text();
   };
   virtual
   void edit() = 0;
protected:
   std::string old_text;
   inline virtual void
   modify(){
     old_text = editor->get_text();
     this->edit();
   }
};
class ACommand : public ModifiedCommand{
public:
    ACommand(std::string str,Editor *editor,Position pos,std::string content)
    :ModifiedCommand(std::move(str),editor){
        this->content = std::move(content);
 	this->pos = pos;
    }
protected:
    inline void 
    edit(){
        editor->add(pos,content);
    };
private:
    std::string content;
    Position pos;
};
class DCommand : public ModifiedCommand{
public:
    DCommand(std::string str,Editor *editor,Position pos,int len)
    :ModifiedCommand(std::move(str),editor){
        this->len = len;
 	this->pos = pos;
    }
protected:
    inline void 
    edit(){
        editor->del(pos,len);
    };
private:
    int len;
    Position pos;
};
class SCommand : public Command{
public:
   SCommand(std::string str,Editor *editor) : Command(std::move(str),editor){
   }
   inline std::string execute(){
     return editor->get_text();
   }
};
#endif
